import os
import time
import asyncio

import django
from celery import shared_task
from django.db import transaction, close_old_connections
from django.db.models import F
from django.utils import timezone
from pymysql import IntegrityError
from celery.utils.log import get_task_logger
from goods.models import SeckillGoods, Goods
from orders.models import Order, SeckillOrder
from fastapi_seckill.redis_fast import RedisHelper

# 初始化 Django 环境
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'seckill_java_topy.settings')
django.setup()

logger = get_task_logger(__name__)


@shared_task(bind=True, max_retries=3)
def createOrder(self, goods_id, user_id):
    """
    创建订单并支持重试机制。
    :param goods_id: 商品 ID
    :param user_id: 用户 ID
    :return: 订单创建结果
    """
    redis = RedisHelper()
    asyncio.run(redis.connect())  # 初始化 Redis 连接
    stock_key = f'seckill_stock:{goods_id}'
    goods_key = f'goods_detail:{goods_id}'
    lock_key = f"lock:order:{goods_id}"

    try:
        # 获取商品信息
        goods_cache = asyncio.run(redis.get_cache(goods_key))
        if not goods_cache:
            logger.error(f"商品 {goods_id} 不存在")
            return {"code": 400, "message": f"商品 ID {goods_id} 不存在"}

        with transaction.atomic():
            # 查询秒杀商品信息
            seckillgoods = None
            for attempt in range(3):  # 最多重试 3 次
                try:
                    seckillgoods = SeckillGoods.objects.select_for_update().get(goods_id=goods_id)
                    break
                except SeckillGoods.DoesNotExist:
                    if attempt == 2:  # 达到最大重试次数
                        logger.error(f"商品 {goods_id} 不存在，已达最大重试次数")
                        raise ValueError("商品不存在")
                    time.sleep(1)  # 等待 1 秒后重试

            # 校验库存
            if seckillgoods.stock_count <= 0:
                logger.error(f"商品 {goods_id} 库存不足")
                raise ValueError("库存不足")

            # 原子扣减 SeckillGoods 库存
            updated = SeckillGoods.objects.filter(
                id=seckillgoods.id,
                stock_count=seckillgoods.stock_count
            ).update(stock_count=F('stock_count') - 1)
            if not updated:
                logger.warning("SeckillGoods 库存更新失败，触发重试")
                raise self.retry(countdown=1)

            # 扣减 Goods 表库存
            goods_updated = Goods.objects.filter(
                id=goods_id
            ).update(goods_stock=F('goods_stock') - 1)
            if not goods_updated:
                logger.warning("Goods 库存更新失败，触发重试")
                raise self.retry(countdown=1)

            # 创建普通订单
            order = Order.objects.create(
                user_id=user_id,
                goods_id=goods_id,
                delivery_addr_id=1,  # 示例：默认地址
                goods_name=goods_cache['name'],
                goods_count=1,
                goods_price=seckillgoods.seckill_price,
                order_channel=1,  # 秒杀渠道
                status=0,  # 待支付
            )

            # 创建秒杀订单并关联普通订单
            seckill_order = SeckillOrder.objects.create(
                user_id=user_id,
                goods_id=goods_id,
                order=order,
            )

            # 记录成功日志
            logger.info(f"订单创建成功: 用户 {user_id}, 商品 {goods_id}, 订单号 {order.id}")
            return {
                "code": 200,
                "message": "订单创建成功",
                "data": {
                    "user_id": user_id,
                    "goods_id": goods_id,
                    "order_id": order.id,
                }
            }

    except SeckillGoods.DoesNotExist:
        logger.error(f"SeckillGoods not found for goods_id: {goods_id}")
        return {"code": 400, "message": "商品不存在"}

    except IntegrityError as e:
        logger.error(f"IntegrityError occurred: {str(e)}")
        return {"code": 400, "message": f"订单创建失败：{str(e)}"}

    except ValueError as e:
        logger.error(f"Failed to create order: {str(e)}")
        return {"code": 400, "message": str(e)}

    except Exception as e:
        logger.error(f"Unexpected error occurred: {str(e)}")
        raise self.retry(exc=e, countdown=1)

    finally:
        close_old_connections()  # 确保关闭数据库连接
        asyncio.run(redis.disconnect())